
module Pan
  
  class Application < Mongrel::HttpHandler
    @@sessions = nil
    
    def self.save_sessions
      # @@sessions.save
    end
    
    def initialize(hostname, port)
      @hostname = hostname
      @port = port
      @lock = Mutex.new
    end
    
    def active_sessions
      @@sessions.size
    end
    
    def ensure_registry
      @@sessions = SessionRegistry.new unless @@sessions
    end
    
    def process(request, response)
      ensure_registry
      begin
        req = Req.new(request)
        res = Res.new(response)
        handle(req, res)
      rescue Exception => e
        puts e.inspect
        pp e.backtrace
      end
    end
    
    def handle(req, res)
      session_id = req.sid
      session = nil
      
      res.header['Server'] = 'Pannonica'
      
      if session_id
        session = @@sessions.find(session_id)
        if session && session.expired?
          session = nil
        end
      else
        session = Dynamic.session_class.new(self)
        session_key = @@sessions.new_session_key()
        @@sessions.register(session,session_key)
        session.session_id = session_key
        ### HACK
        session.snapshot_all("0000")
        
        res.redirect_303("#{req.public_url}/#{session_key}#{session.new_view_id()}")
        return
      end
      
      if session
        session.handle(req, res)
      else
        res.redirect_302(req.public_url)
      end
    end

    class << self
      
      def dynamics 
        Dynamic.variable :current_response => nil
        Dynamic.variable :current_session  => nil
        Dynamic.variable :current_viewid   => nil
        Dynamic.variable :session_class    => nil
        Dynamic.variable :current_form     => nil
        Dynamic.variable :current_req      => nil
        Dynamic.variable :current_res      => nil
        Dynamic.variable :entry_point      => nil
      end
      
      def create_server(hostname, port, entry_point, mount_points)
        threads = 1
        server = Mongrel::HttpServer.new(hostname, port, threads)
        server.register(entry_point, Application.new(hostname, port))
        mount_points.each do |uri,dir|
          puts "mounting #{dir} as #{uri}"
          server.register(uri, Mongrel::DirHandler.new(dir,true))
        end
        # server.register("/", Mongrel::DirHandler.new("public",true))
        server
      end
      
      ### MAIN
      
      def start_application(hostname, port, entry_point, session_class, mount_points)
        dynamics()
        Dynamic.let(:session_class => session_class, :entry_point=>entry_point) do
          server = create_server(hostname, port, entry_point, mount_points)
          trap("INT") { 
            # Application.save_sessions
            print "Shutting down..."
            $stdout.flush
            server.stop 
            puts "done"
            Pan::log("Shut down")
          } 
          puts "Started..."
          Pan::log("Started")
          server.run.join
        end
      end 
    end
  end
end
